﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WLYT.Application.Interfaces;
using WLYT.Common;
using WLYT.Domain.Entries;
using WLYT.Domain.Model;

namespace WLYT.Application.Services
{
    public class RouteService(IBaseService<Sys_Menus> sysMenusService,
                              IBaseService<Sys_Role> sysRoleService,
                              IBaseService<Sys_Operation> sysOperationService,
                              IHttpContextAccessor httpContextAccessor) : IRouteService
    {
        public async Task<List<RouteItem>> RouteTreeLoad()
        {
            var result = await GetMenus();
            IList<Sys_Menus> menus = result.Item1;
            IList<Sys_Operation> operations = result.Item2;

            IList<Sys_Menus> parentRouteData = menus.Where(r => r.MenuParentId == 0).OrderBy(m => m.Sort).ThenBy(s => s.Id).ToList();

            List<RouteItem> routeData = new List<RouteItem>();

            foreach (RouteItem item in parentRouteData.Select(m => new RouteItem
            {
                router = m.MenuPageUrl,
                id = m.Id,
                children = new List<RouteItem>()
            }))
            {
                RouteChildListLoad(item, menus, operations);
                routeData.Add(item);
            }
            return routeData;
        }

        private async Task<Tuple<IList<Sys_Menus>, IList<Sys_Operation>>> GetMenus()
        {
            var user = JwtHelper.GetTokenPayload(httpContextAccessor.HttpContext);
            var role = await sysRoleService.GetByIdAsync(user.RoleId);
            List<string> roles = role.Permission.Split(',').ToList();

            List<Sys_Operation> operationList = new List<Sys_Operation>();

            List<Sys_Menus> menus = await sysMenusService.GetListAsync(true);
            var newMenu = new List<Sys_Menus>();
            if (!roles.Any(item => item == "*"))
            {
                foreach (var item in roles)
                {
                    string page = item.Split('_').FirstOrDefault();
                    var menu = menus.FirstOrDefault(p => p.MenuPageUrl == page);
                    if (menu != null && !newMenu.Contains(menu))
                    {
                        newMenu.Add(menu);
                        var parentMenu = menus.FirstOrDefault(p => p.Id == menu.MenuParentId);
                        if (parentMenu != null && !newMenu.Contains(parentMenu))
                        {
                            newMenu.Add(parentMenu);
                        }
                    }
                }

                IList<string> operations = roles.Where(p => p.Contains("_")).ToList();
                foreach (var item in operations)
                {
                    operationList.Add(new Sys_Operation
                    {
                        Code = item.Split('_').LastOrDefault(),
                        MenuUrl = item.Split('_').FirstOrDefault(),
                    });
                }
            }
            else
            {
                newMenu = menus;
                operationList = await sysOperationService.GetListAsync(true);
            }
            return new Tuple<IList<Sys_Menus>, IList<Sys_Operation>>(newMenu, operationList);
        }

        private void RouteChildListLoad(RouteItem sItem, IList<Sys_Menus> menus, IList<Sys_Operation> operations)
        {
            List<Sys_Menus> childRoutes = menus.Where(r => r.MenuParentId == sItem.id).OrderBy(s => s.Sort).ThenBy(s => s.Id).ToList();

            foreach (RouteItem item in childRoutes.Select(item => new RouteItem
            {
                id = item.Id,
                router = item.MenuPageUrl,
                name = item.MenuName,
                children = new List<RouteItem>(),
                authority = GetAuthority(item.MenuPageUrl, operations),
            }))
            {
                RouteChildListLoad(item, menus, operations);
                sItem.children.Add(item);
            }
        }

        private string GetAuthority(string path, IList<Sys_Operation> operations)
        {
            return operations.Any(p => p.MenuUrl == path) ? path : null;
        }
    }
}
